From fcddf6d32c10639e765166eccc07e78e0623e905 Mon Sep 17 00:00:00 2001 From: Xisco Fauli Date: Fri, 17 Jul 2026 11:59:00 +0200 Subject: [PATCH] [PATCH] Reapply "firebird: keep each embedded database's files in one directory" This reverts commit 23a5d0dc305fc04bdd277b24db8d5c8e41aa9ccd. it also contains https://gerrit.collaboraoffice.com/c/core/+/7093 "firebird: upper-case the DatabaseAccess Restrict path on Windows" Change-Id: I52ea962a51da19a112892d6a2497a7ddf682c579 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208212 Tested-by: Jenkins Reviewed-by: Xisco Fauli (cherry picked from commit e4dc6a3cb2bfbf9d4c1e30e777b0f46417cf4c92) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208224 Reviewed-by: Ilmari Lauhakangas Tested-by: Ilmari Lauhakangas Reviewed-by: Hossein Gbp-Pq: Name CVE-2026-63266-2.diff --- .../source/drivers/firebird/Connection.cxx | 5 +- .../source/drivers/firebird/Connection.hxx | 3 +- .../source/drivers/firebird/Driver.cxx | 52 ++++++++++++++++++- .../source/drivers/firebird/Driver.hxx | 7 +++ 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/connectivity/source/drivers/firebird/Connection.cxx b/connectivity/source/drivers/firebird/Connection.cxx index ddeaa249e54..9ab978726d9 100644 --- a/connectivity/source/drivers/firebird/Connection.cxx +++ b/connectivity/source/drivers/firebird/Connection.cxx @@ -121,7 +121,8 @@ struct ConnectionGuard } -void Connection::construct(const OUString& url, const Sequence< PropertyValue >& info) +void Connection::construct(const OUString& url, const Sequence< PropertyValue >& info, + const OUString& rDatabaseDataDirectoryURL) { ConnectionGuard aGuard(m_refCount); @@ -161,7 +162,7 @@ void Connection::construct(const OUString& url, const Sequence< PropertyValue >& bIsNewDatabase = !m_xEmbeddedStorage->hasElements(); - m_pDatabaseFileDir.reset(new ::utl::TempFileNamed(nullptr, true)); + m_pDatabaseFileDir.reset(new ::utl::TempFileNamed(&rDatabaseDataDirectoryURL, true)); m_pDatabaseFileDir->EnableKillingFile(); m_sFirebirdURL = m_pDatabaseFileDir->GetFileName() + "/firebird.fdb"; m_sFBKPath = m_pDatabaseFileDir->GetFileName() + "/firebird.fbk"; diff --git a/connectivity/source/drivers/firebird/Connection.hxx b/connectivity/source/drivers/firebird/Connection.hxx index 16ac0ffa278..fb142283c72 100644 --- a/connectivity/source/drivers/firebird/Connection.hxx +++ b/connectivity/source/drivers/firebird/Connection.hxx @@ -163,7 +163,8 @@ namespace connectivity::firebird /// @throws css::sdbc::SQLException /// @throws css::uno::RuntimeException void construct( const OUString& url, - const css::uno::Sequence< css::beans::PropertyValue >& info); + const css::uno::Sequence< css::beans::PropertyValue >& info, + const OUString& rDatabaseDataDirectoryURL); const OUString& getConnectionURL() const {return m_sConnectionURL;} bool isEmbedded() const {return m_bIsEmbedded;} diff --git a/connectivity/source/drivers/firebird/Driver.cxx b/connectivity/source/drivers/firebird/Driver.cxx index 167072ca71c..1f345d772ac 100644 --- a/connectivity/source/drivers/firebird/Driver.cxx +++ b/connectivity/source/drivers/firebird/Driver.cxx @@ -48,6 +48,7 @@ namespace { constexpr OUString our_sFirebirdTmpVar = u"FIREBIRD_TMP"_ustr; constexpr OUString our_sFirebirdLockVar = u"FIREBIRD_LOCK"_ustr; constexpr OUString our_sFirebirdMsgVar = u"FIREBIRD_MSG"_ustr; +constexpr OUString our_sFirebirdRootVar = u"FIREBIRD"_ustr; #ifdef MACOSX constexpr OUString our_sFirebirdLibVar = u"LIBREOFFICE_FIREBIRD_LIB"_ustr; #endif @@ -58,12 +59,15 @@ FirebirdDriver::FirebirdDriver(const css::uno::Reference< css::uno::XComponentCo , m_aContext(_rxContext) , m_firebirdTMPDirectory(nullptr, true) , m_firebirdLockDirectory(nullptr, true) + , m_firebirdDataDirectory(nullptr, true) + , m_bConfined(false) { // ::utl::TempFile uses a unique temporary directory (subdirectory of // /tmp or other user specific tmp directory) per instance in which // we can create directories for firebird at will. m_firebirdTMPDirectory.EnableKillingFile(true); m_firebirdLockDirectory.EnableKillingFile(true); + m_firebirdDataDirectory.EnableKillingFile(true); // Overrides firebird's default of /tmp or c:\temp osl_setEnvironment(our_sFirebirdTmpVar.pData, m_firebirdTMPDirectory.GetFileName().pData); @@ -71,6 +75,41 @@ FirebirdDriver::FirebirdDriver(const css::uno::Reference< css::uno::XComponentCo // Overrides firebird's default of /tmp/firebird or c:\temp\firebird osl_setEnvironment(our_sFirebirdLockVar.pData, m_firebirdLockDirectory.GetFileName().pData); + // Keep the files firebird opens or creates together in one directory. + // Embedded databases are extracted here, and DatabaseAccess = Restrict + // keeps any associated files firebird makes for it under the same + // directory. firebird reads this firebird.conf from the directory the + // FIREBIRD variable names, once, on its first use, so it has to be set + // before the first connection. + OUString sDataDirPath; + ::osl::FileBase::getSystemPathFromFileURL(m_firebirdDataDirectory.GetURL(), sDataDirPath); + +#if defined(_WIN32) + // firebird upper-cases the database path before the exact-match + // DatabaseAccess check, so match that here. + sDataDirPath = sDataDirPath.toAsciiUpperCase(); +#endif + + OString sConf = "DatabaseAccess = Restrict " + + OUStringToOString(sDataDirPath, RTL_TEXTENCODING_UTF8) + "\n"; + + OUString sConfURL = m_firebirdDataDirectory.GetURL() + "/firebird.conf"; + ::osl::File aConfFile(sConfURL); + if (aConfFile.open(osl_File_OpenFlag_Create | osl_File_OpenFlag_Write) == ::osl::FileBase::E_None) + { + sal_uInt64 nWritten = 0; + if (aConfFile.write(sConf.getStr(), sConf.getLength(), nWritten) == ::osl::FileBase::E_None + && nWritten == static_cast(sConf.getLength())) + { + osl_setEnvironment(our_sFirebirdRootVar.pData, sDataDirPath.pData); + m_bConfined = true; + } + aConfFile.close(); + } + + SAL_WARN_IF(!m_bConfined, "connectivity.firebird", + "could not write " << sConfURL << ", firebird connections will be refused"); + #ifndef SYSTEM_FIREBIRD // Overrides firebird's hardcoded default of /usr/local/firebird on *nix, // however on Windows it seems to use the current directory as a default. @@ -107,6 +146,7 @@ void FirebirdDriver::disposing() osl_clearEnvironment(our_sFirebirdTmpVar.pData); osl_clearEnvironment(our_sFirebirdLockVar.pData); + osl_clearEnvironment(our_sFirebirdRootVar.pData); #ifndef SYSTEM_FIREBIRD osl_clearEnvironment(our_sFirebirdMsgVar.pData); @@ -148,8 +188,18 @@ Reference< XConnection > SAL_CALL FirebirdDriver::connect( if ( ! acceptsURL(url) ) return nullptr; + // Without the firebird.conf that keeps firebird inside its own directory + // we do not open any database. + if (!m_bConfined) + { + ::connectivity::SharedResources aResources; + const OUString sMessage = aResources.getResourceString(STR_COULD_NOT_LOAD_FILE).replaceFirst( + "$filename$", u"firebird.conf"); + ::dbtools::throwGenericSQLException(sMessage, *this); + } + rtl::Reference pCon = new Connection(); - pCon->construct(url, info); + pCon->construct(url, info, getDatabaseDataDirectoryURL()); m_xConnections.emplace_back(*pCon); diff --git a/connectivity/source/drivers/firebird/Driver.hxx b/connectivity/source/drivers/firebird/Driver.hxx index d884b5008d6..0f5172f6222 100644 --- a/connectivity/source/drivers/firebird/Driver.hxx +++ b/connectivity/source/drivers/firebird/Driver.hxx @@ -47,6 +47,8 @@ namespace connectivity::firebird css::uno::Reference m_aContext; ::utl::TempFileNamed m_firebirdTMPDirectory; ::utl::TempFileNamed m_firebirdLockDirectory; + ::utl::TempFileNamed m_firebirdDataDirectory; + bool m_bConfined; protected: ::osl::Mutex m_aMutex; // mutex is need to control member access @@ -60,6 +62,11 @@ namespace connectivity::firebird virtual ~FirebirdDriver() override; const css::uno::Reference& getContext() const { return m_aContext; } + // The directory that embedded databases are extracted into. Each + // connection makes its own subdirectory here, and firebird keeps + // associated files it creates for them under this directory as well. + OUString getDatabaseDataDirectoryURL() const { return m_firebirdDataDirectory.GetURL(); } + // OComponentHelper virtual void SAL_CALL disposing() override; -- 2.39.5